#include "HistoryManager.h"
#include <iostream>
#include "Core/MainWindow.h"
#include "FeatureShape.h"
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <BRepPrimAPI_MakeRevol.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include "Expression/ExpressionManager.h"
#include <ctime>
#include <vtkProperty.h>
#include "Widget/Operation/QFillOperationWidget.h"
#include "Serialize/RWShapeSerializeManager.h"
#include "Core/RWGeometryTool.h"

HistoryManager::HistoryManager(QStandardItemModel* listModel, QListView* listView, MainWindow* mainWindow)
    : m_listModel(listModel)
    , m_listView(listView)
    , m_mainWindow(mainWindow)
{
    m_currentVersion = new QShapeVersion();
    m_expressionManager = new ExpressionManager(this);

    connect(m_listView, &QListView::doubleClicked, this, &HistoryManager::onItemDoubleClicked);
    connect(m_listView, &QListView::clicked, this, &HistoryManager::onItemClicked);
    connect(m_mainWindow, &MainWindow::OnLeftButtonDown, this, &HistoryManager::OnLeftButtonDown);
    connect(m_listModel, &QStandardItemModel::itemChanged, this, &HistoryManager::onItemChanged);

	// 初始化定时器（略长于系统双击间隔）
	clickTimer = new QTimer(this);
	clickTimer->setSingleShot(true);
	clickTimer->setInterval(QApplication::doubleClickInterval() + 15);
    //std::cout << "clickTimer->setInterval() = " << clickTimer->interval() << std::endl; //延迟有点高了
    connect(clickTimer, &QTimer::timeout, this, &HistoryManager::processSingleClick);

    m_startTime = std::time(nullptr);
}

void HistoryManager::applyOperation(ShapeOperation* op)
{
	if (tempActor)
	{
		m_mainWindow->RemoveActorFromRenderer(tempActor);
	}

    if (op == nullptr)
    {
        qDebug() << "Operation is null";
        return;
    }

    bIsDirty = true;
    bIsModify = true;

    // 处于连续回溯version中
    if (bIsRedo)
    {
        // 已经完成了点击version的redo，这里只需记录信息
        delete m_currentVersion->m_operation;
        m_currentVersion->m_operation = op;
		historyVersion.push_back(m_currentVersion);
        // 按理说futureVersion在这里的size至少为1
		if (futureVersion.size())
		{
            // 历史流item
			//QStandardItem* item(new QStandardItem(op->operationName));
            //item->setCheckable(true);
            //item->setCheckState(Qt::Checked);
			//item->setTextAlignment(Qt::AlignCenter);
			//item->setData(QVariant::fromValue<QPointer<QShapeVersion>>(m_currentVersion), Qt::UserRole);
			//m_listModel->appendRow(item);
            redoUpdateItemState();

            // 准备继续回溯version
			m_currentVersion = futureVersion.back();
			m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();
			m_currentVersion->m_featureShapes = m_currentFeatureShapes;
			futureVersion.pop_back();
		}
        else
        {
            std::cout << "HistoryManager::applyOperation--->future Version size = 0! must have some error" << std::endl;
        }

        // 剩余version的redo
        while (m_itemIndex <= RedoTargetIndex  && redo())
        {
            // std::cout << "redo successfil" << std::endl;
        }

        bIsRedo = false;
        RedoTargetIndex = -1;
        return;
    }

	// 移除未重做的version
	if (!isLatestVersion())
	{
		while (!isLatestVersion())
		{
			m_listModel->removeRow(m_listModel->rowCount() - 1);
		}
	}

    // 重新修改，清空未完成操作
    futureVersion.clear();

    m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();

    // 历史流item
    m_currentVersion->m_operation = op;
    QStandardItem* item(new QStandardItem(op->operationName));
    item->setCheckable(true);
    item->setCheckState(Qt::Checked);
    item->setTextAlignment(Qt::AlignCenter);
    item->setData(QVariant::fromValue<QPointer<QShapeVersion>>(m_currentVersion), Qt::UserRole);
    m_listModel->appendRow(item);
	m_itemIndex++;

    // 表达式
    m_expressionManager->AddExpression(m_currentVersion);

    historyVersion.append(m_currentVersion);
    m_currentVersion = new QShapeVersion();
    m_currentVersion->m_featureShapes = m_currentFeatureShapes;
}

bool HistoryManager::undo(bool bRemoveHistoryItem)
{
    if (historyVersion.size() == 0)
    {
        return false;
    }

    bIsDirty = true;

    // 清空所有actors
    m_mainWindow->RemoveAllActorsFromRenderer();

    //if (bRemoveHistoryItem && m_itemIndex == m_listModel->rowCount() - 1)
    //{
    //    m_listModel->removeRow(m_listModel->rowCount() - 1);
    //}

    undoUpdateItemState();

    futureVersion.push_back(m_currentVersion);
    m_currentVersion = historyVersion.back();
    historyVersion.pop_back();

    for (auto& item : m_currentVersion->m_featureShapes)
    {
        Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createBasicUnitActor(item->_shape, true);
        actor->m_featureShape = item;
    }

    m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();

    return true;
}

bool HistoryManager::redo(bool bAddHistoryItem)
{
    // 无法重做
    if (!m_currentVersion->m_operation)
    {
        return false;
    }

    bIsDirty = true;

    redoUpdateItemState();

    bool bIsSuccess = false;

    // 通过type确定子类，所以用static_cast（更省性能）
    if (m_currentVersion->m_operation->m_operationType == EOperationType::Create)
    {
        bIsSuccess = redoCreateShape(static_cast<CreateShapeOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Boolean)
    {
        bIsSuccess = redoBooleanShape(static_cast<BooleanOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Delete)
    {
        bIsSuccess = redoDeleteShape(static_cast<DeleteShapeOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Hollow)
    {
        bIsSuccess = redoHollowShape(static_cast<HollowOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Transform)
    {
        bIsSuccess = redoTransformShape(static_cast<TransformOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Stretch)
    {
        bIsSuccess = redoStretchShape(static_cast<StretchOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Revolve)
    {
        bIsSuccess = redoRevolveShape(static_cast<RevolveOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::RoundOff)
    {
        bIsSuccess = redoRoundOffShape(static_cast<RoundOffOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Sketch)
    {
        bIsSuccess = redoSketch(static_cast<SketchOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::FillFace)
    {
        bIsSuccess = redoFillFace(static_cast<FillFaceOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::CreateFromObject)
    {
        bIsSuccess = redoCreateFromObject(static_cast<CreateShapeFromObjectOperatopn*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::DetachEdge)
    {
        bIsSuccess = redoDetachEdge(static_cast<DetachEdgeOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::DetachFace)
    {
        bIsSuccess = redoDetachFace(static_cast<DetachFaceOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::UncoverFace)
    {
        bIsSuccess = redoUncoverFace(static_cast<UncoverFaceOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::CoverFace)
    {
        bIsSuccess = redoCoverFace(static_cast<CoverFaceOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::MoveEdge)
    {
        bIsSuccess = redoMoveEdge(static_cast<MoveEdgeOperation*>(m_currentVersion->m_operation));
    }
	else if (m_currentVersion->m_operation->m_operationType == EOperationType::MoveFace)
    {
        bIsSuccess = redoMoveFace(static_cast<MoveFaceOperation*>(m_currentVersion->m_operation));
    }
    else if (m_currentVersion->m_operation->m_operationType == EOperationType::Section)
    {
        bIsSuccess = redoSection(static_cast<SectionOperation*>(m_currentVersion->m_operation));
    }
    else
    {
        std::cout << "HistoryManager::redo: Unknown operation type" << std::endl;
    }

    m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();

    historyVersion.push_back(m_currentVersion);
    // 正常会走这里的逻辑
    if (futureVersion.size())
    {
        m_currentVersion = futureVersion.back();
        m_currentVersion->m_featureShapes = m_currentFeatureShapes;
        futureVersion.pop_back();
    }
    // load会走这里
    else
    {
        m_currentVersion = new QShapeVersion();
        m_currentVersion->m_featureShapes = m_currentFeatureShapes;
    }

    return bIsSuccess;
}

void HistoryManager::ModifyVersion(uint versionID)
{
    // 1. 找到对应的version
    // 2. 回溯version
    // 3. redo

    // 找到对应的version
    auto targetVersion = std::find_if(historyVersion.begin(), historyVersion.end(), 
        [versionID](QPointer<QShapeVersion> version)
        {
            return version->GetVersionID() == versionID;
        });
    if (targetVersion == historyVersion.end())
    {
        std::cout << "HistoryManager::ModifyVersion--->target version is not found." << std::endl;
        return;
    }

	// 退回到version
	m_mainWindow->RemoveAllActorsFromRenderer();
	while (historyVersion.back()->GetVersionID() != versionID)
	{
		futureVersion.push_back(m_currentVersion);
		m_currentVersion = historyVersion.back();
		historyVersion.pop_back();
	}
	futureVersion.push_back(m_currentVersion);
	m_currentVersion = historyVersion.back();
	historyVersion.pop_back();

	// 创建对应version的actor
	for (auto& item : m_currentVersion->m_featureShapes)
	{
		Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createBasicUnitActor(item->_shape, true);
		actor->m_featureShape = item;
	}
	m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();

    // redo
    while (redo(false))
    {
        // std::cout << "HistoryManager::ModifyVersion--->redo." << std::endl;
    }
}

void HistoryManager::OnOperationCancel()
{
    if (!bIsRedo)
    {
        return;
    }

    bIsRedo = false;
    // std::cout << "HistoryManager::OnOperationCancel" << std::endl;
    while (redo()) {};
}

void HistoryManager::OnLeftButtonDown()
{
	if (tempActor)
	{
		m_mainWindow->RemoveActorFromRenderer(tempActor);
	}
}

void HistoryManager::onItemChanged(QStandardItem* item)
{
    //std::cout << "onItemChanged" << std::endl;
    if (bNotOccurItemChangeEvent)
    {
        return;
    }
	if (tempActor)
	{
		m_mainWindow->RemoveActorFromRenderer(tempActor);
	}
    bNotOccurItemChangeEvent = true;
    auto index = m_listModel->indexFromItem(item);
	int old = m_itemIndex;
	// history的version全部redo
    if (item->checkState() == Qt::Checked)
    {
		for (int row = old + 1; row <= index.row(); ++row)
        {
            redo(false);
		}
    }
    // future的version全部undo
    else if(item->checkState() == Qt::Unchecked)
    {
		for (int row = old; row >= index.row(); --row)
		{
            undo(false);
		}
    }
    bNotOccurItemChangeEvent = false;
    bItemChangedEventOccurred = true;
}

void HistoryManager::EditActor(Handle(QIVtkSelectionPipeline) actor)
{
    editVersion(getVersion(actor));
}

bool HistoryManager::redoCreateShape(CreateShapeOperation* op)
{
    Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createActorFromFeatureShape(op->m_featureShape.get(), true);
    if (actor)
    {
        actor->m_featureShape = op->m_featureShape;
        return true;
    }
    return false;
}

bool HistoryManager::redoBooleanShape(BooleanOperation* op)
{
    if (op->m_targetShape < 0 || op->m_toolShape < 0 || op->m_targetShape >= m_currentFeatureShapes.size() || op->m_toolShape >= m_currentFeatureShapes.size())
    {
        std::cout << "redoBooleanShape invalid index." << std::endl;
        return false;
    }

    TopoDS_Shape resultShape = MainWindow::BooleanOperation(m_currentFeatureShapes[op->m_targetShape]->_shape,
        m_currentFeatureShapes[op->m_toolShape]->_shape, op->m_booleanStyle);
    if (resultShape.IsNull())
    {
        return false;
    }

    Handle(QIVtkSelectionPipeline) targetActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_targetShape);
    Handle(QIVtkSelectionPipeline) toolActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_toolShape);

    if (!targetActor || !toolActor)
    {
        return false;
    }

    m_mainWindow->RemoveActorFromRenderer(targetActor);
    m_mainWindow->RemoveActorFromRenderer(toolActor);

    Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createBasicUnitActor(resultShape, true);
    if (!actor)
    {
        return false;
    }
    actor->m_featureShape = std::make_shared<FeatureShapeMix>(resultShape);
    return true;
}

bool HistoryManager::redoDeleteShape(DeleteShapeOperation* op)
{
    std::vector<Handle(QIVtkSelectionPipeline)> deleteActors;
    for (const auto& item : op->m_shapeIndex)
    {
        Handle(QIVtkSelectionPipeline) actor = GetActorFromIndex(m_mainWindow->GetCachedActors(), item);
        if (!actor)
        {
            return false;
        }
        deleteActors.push_back(actor);
    }
    while (deleteActors.size())
    {
        m_mainWindow->RemoveActorFromRenderer(deleteActors.back());
        deleteActors.pop_back();
    }
    return true;
}

bool HistoryManager::redoHollowShape(HollowOperation* op)
{
    Handle(QIVtkSelectionPipeline) hollowActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
    if (!hollowActor)
    {
        std::cout << "redoHollowShape invalid index." << std::endl;
        return false;
    }
    TopTools_ListOfShape facesToRemove;
	int i = 0;
	for (TopExp_Explorer explorer(hollowActor->OccShape(), TopAbs_FACE); explorer.More(); explorer.Next(), i++)
	{
		if (std::find(op->m_subFaceIndex.begin(), op->m_subFaceIndex.end(), i) != op->m_subFaceIndex.end())
		{
            facesToRemove.Append(explorer.Current());
		}

		if (i >= op->m_subFaceIndex.back())
		{
			break;
		}
	}

    if (facesToRemove.IsEmpty())
    {
        return false;
    }

	BRepOffsetAPI_MakeThickSolid hollowMaker;
	hollowMaker.MakeThickSolidByJoin(hollowActor->OccShape(), facesToRemove, op->m_thickness, Precision::Confusion());
	hollowMaker.Build();
	if (hollowMaker.Shape().IsNull())
	{
		std::cout << "redoHollowShape failed." << std::endl;
		return false;
	}

    Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(hollowMaker.Shape(), true);
    if (!newActor)
    {
        return false;
    }
	newActor->m_position = hollowActor->m_position;
	m_mainWindow->RemoveActorFromRenderer(hollowActor);
	newActor->m_featureShape.reset(new FeatureShapeMix(hollowMaker.Shape()));
    return true;
}

bool HistoryManager::redoTransformShape(TransformOperation* op)
{
    std::vector<Handle(QIVtkSelectionPipeline)> transformActors;
    for (const auto& item : op->m_shapeIndex)
    {
        transformActors.push_back(GetActorFromIndex(m_mainWindow->GetCachedActors(), item));
    }

    for (Handle(QIVtkSelectionPipeline) actor : transformActors)
    {
        Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->TransformActor(actor, op->m_transform, true);
        if (!newActor)
        {
            return false;
        }
		newActor->m_featureShape.reset(new FeatureShapeMix(newActor->OccShape()));
		newActor->m_featureShape->_position = newActor->m_position;
    }
    return true;
}

bool HistoryManager::redoStretchShape(StretchOperation* op)
{
    Handle(QIVtkSelectionPipeline) stretchActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
    if (!stretchActor)
    {
        std::cout << "redoStretchShape invalid index." << std::endl;
        return false;
    }
    // use std::reference_wrapper<const TopoDS_Shape> 会触发崩溃
    std::vector<TopoDS_Shape> m_shapelist;

    TopAbs_ShapeEnum shapeType = op->m_bIsEdge ? TopAbs_EDGE : TopAbs_FACE;
    int i = 0;
    for (TopExp_Explorer explorer(stretchActor->OccShape(), shapeType); explorer.More(); explorer.Next(), i++)
    {
		if (i > op->m_subShapeIndex.back())
		{
			break;
		}

        if (std::find(op->m_subShapeIndex.begin(), op->m_subShapeIndex.end(), i) != op->m_subShapeIndex.end())
        {
            m_shapelist.push_back(explorer.Current());
        }
	}

    if (m_shapelist.empty())
    {
        return false;
    }

	// 尝试将选择的边转化为face
	TopoDS_Face face;
	if (m_shapelist[0].ShapeType() == TopAbs_EDGE)
	{
		std::vector<TopoDS_Edge> selectEdges;
		for (int i = 0; i < m_shapelist.size(); i++)
		{
			if (m_shapelist[i].ShapeType() == TopAbs_EDGE)
			{
				selectEdges.push_back(TopoDS::Edge(m_shapelist[i]));
			}
		}
		std::vector<TopoDS_Wire> wires = QFillOperationWidget::BuildWiresFromEdges(selectEdges);
		if (wires.size())
		{
			face = QFillOperationWidget::CreateFaceWithHoles(wires);
		}
	}
	TopoDS_Shape resultShape;
	if (face.IsNull())
	{
		BRepPrimAPI_MakePrism prismShape(m_shapelist[0], op->m_stretchVector);
		resultShape = prismShape.Shape();

		for (int i = 1; i < m_shapelist.size(); i++)
		{
			BRepPrimAPI_MakePrism tempPrismShape(m_shapelist[i], op->m_stretchVector);
			resultShape = m_mainWindow->BooleanOperation(resultShape, tempPrismShape, BooleanOP::Union);
		}
	}
	else
	{
		BRepPrimAPI_MakePrism prismShape(face, op->m_stretchVector);
		resultShape = prismShape.Shape();
	}

	if (resultShape.IsNull())
	{
		std::cout << "redo stretch failed" << std::endl;
		return false;
	}

    Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(resultShape, true);
    if (!newActor)
    {
        return false;
    }
	newActor->m_featureShape.reset(new FeatureShapeMix(resultShape));
    return true;
}

bool HistoryManager::redoRevolveShape(RevolveOperation* op)
{
	Handle(QIVtkSelectionPipeline) revolveActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
	if (!revolveActor)
	{
		std::cout << "redoRevolveShape invalid index." << std::endl;
		return false;
	}

    std::vector<TopoDS_Shape> m_shapelist;

	TopAbs_ShapeEnum shapeType = op->m_bUseEdge ? TopAbs_EDGE : TopAbs_FACE;
	int i = 0;
	for (TopExp_Explorer explorer(revolveActor->OccShape(), shapeType); explorer.More(); explorer.Next(), i++)
	{
		if (std::find(op->m_subShapeIndex.begin(), op->m_subShapeIndex.end(), i) != op->m_subShapeIndex.end())
		{
			m_shapelist.push_back(explorer.Current());
		}

		if (i >= op->m_subShapeIndex.back())
		{
			break;
		}
	}

	if (m_shapelist.empty())
	{
		return false;
	}

	// 尝试将选择的边转化为face
	TopoDS_Face face;
	if (m_shapelist[0].ShapeType() == TopAbs_EDGE)
	{
		std::vector<TopoDS_Edge> selectEdges;
		for (int i = 0; i < m_shapelist.size(); i++)
		{
			if (m_shapelist[i].ShapeType() == TopAbs_EDGE)
			{
				selectEdges.push_back(TopoDS::Edge(m_shapelist[i]));
			}
		}
		std::vector<TopoDS_Wire> wires = QFillOperationWidget::BuildWiresFromEdges(selectEdges);
		if (wires.size())
		{
			face = QFillOperationWidget::CreateFaceWithHoles(wires);
		}
	}
	TopoDS_Shape revolvedShape;
	if (face.IsNull())
	{
		revolvedShape = BRepPrimAPI_MakeRevol(m_shapelist[0], op->m_rotationAxis, op->m_angle * M_PI / 180).Shape();

		for (int i = 1; i < m_shapelist.size(); i++)
		{
			TopoDS_Shape tempRevolvedShape = BRepPrimAPI_MakeRevol(m_shapelist[i], op->m_rotationAxis, op->m_angle * M_PI / 180).Shape();
			revolvedShape = m_mainWindow->BooleanOperation(revolvedShape, tempRevolvedShape, BooleanOP::Union);
		}
	}
	else
	{
		revolvedShape = BRepPrimAPI_MakeRevol(face, op->m_rotationAxis, op->m_angle * M_PI / 180).Shape();
	}

	if (revolvedShape.IsNull())
	{
        std::cout << "redo revolve failed" << std::endl;
		return false;
	}

    Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(revolvedShape, true);
	if (!newActor)
    {
        return false;
    }
	newActor->m_featureShape.reset(new FeatureShapeMix(revolvedShape));
    return true;
}

bool HistoryManager::redoRoundOffShape(RoundOffOperation* op)
{
    Handle(QIVtkSelectionPipeline) roundOffActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
    if (!roundOffActor)
    {
        std::cout << "redoHollowShape invalid index." << std::endl;
        return false;
    }

    BRepFilletAPI_MakeFillet filletMaker(roundOffActor->OccShape());
    int i = 0;
    for (TopExp_Explorer explorer(roundOffActor->OccShape(), TopAbs_EDGE); explorer.More(); explorer.Next(), i++)
    {
        if (std::find(op->m_subShapeIndex.begin(), op->m_subShapeIndex.end(), i) != op->m_subShapeIndex.end())
        {
            filletMaker.Add(op->m_radius, TopoDS::Edge(explorer.Current()));
        }

        if (i >= op->m_subShapeIndex.back())
        {
            break;
        }
    }

    filletMaker.Build();
    if (filletMaker.Shape().IsNull())
    {
        std::cout << "redoRoundOffShape failed." << std::endl;
        return false;
    }

    Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(filletMaker.Shape(), true);
    if (!newActor)
    {
        return false;
    }
	newActor->m_position = roundOffActor->m_position;
	m_mainWindow->RemoveActorFromRenderer(roundOffActor);
	newActor->m_featureShape.reset(new FeatureShapeMix(filletMaker.Shape()));
    return true;
}

bool HistoryManager::redoSketch(SketchOperation* op)
{
    for (auto& shape : op->m_featureShapes)
    {
		Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createActorFromFeatureShape(shape.get(), true);
        if (!actor)
        {
            std::cout << "redoSketch failed." << std::endl;
            return false;
        }
        actor->m_featureShape = shape;
    }

    return true;
}

bool HistoryManager::redoFillFace(FillFaceOperation* op)
{
    std::vector<TopoDS_Edge> edges;

    for (int i = 0; i < op->m_shapeIndex.size(); i++)
    {
        Handle(QIVtkSelectionPipeline) actor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex[i].first);
		int j = 0;
		for (TopExp_Explorer explorer(actor->OccShape(), TopAbs_EDGE); explorer.More(); explorer.Next(), j++)
		{
			if (j > op->m_shapeIndex[i].second.back())
			{
				break;
			}

			if (std::find(op->m_shapeIndex[i].second.begin(), op->m_shapeIndex[i].second.end(), j) != op->m_shapeIndex[i].second.end())
			{
                edges.push_back(TopoDS::Edge(explorer.Current()));
			}
		}

		if (edges.empty())
		{
			return false;
		}
    }

	// 1.将edge转化为wire
	std::cout << "QFillOperationWidget::Edge Num:" << edges.size() << std::endl;
	std::vector<TopoDS_Wire> wires = QFillOperationWidget::BuildWiresFromEdges(edges);
	std::cout << "QFillOperationWidget::HandleWire Num:" << wires.size() << std::endl;
	// 2.将wire转化为face
	TopoDS_Face face = QFillOperationWidget::CreateFaceWithHoles(wires);
	// 3.根据face生成actor
	Handle(QIVtkSelectionPipeline) faceActor = m_mainWindow->createBasicUnitActor(face, true);

    if (!faceActor)
    {
        return false;
    }
    faceActor->m_featureShape.reset(new FeatureShapeMix(face));
    return true;
}

bool HistoryManager::redoCreateFromObject(CreateShapeFromObjectOperatopn* op)
{
    Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
    TopAbs_ShapeEnum shapeType = op->bUseEdge ? TopAbs_EDGE : TopAbs_FACE;
    TopoDS_Shape shape;
	int i = 0;
	for (TopExp_Explorer explorer(refActor->OccShape(), shapeType); explorer.More(); explorer.Next(), i++)
	{
        if (i == op->m_subShapeIndex)
        {
            shape = explorer.Current();
            break;
        }
	}

    if (shape.IsNull())
    {
        std::cout << "redoCreateFromObject faild. Shape is null" << std::endl;
        return false;
    }

	Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(shape, true);
	if (!newActor)
	{
		return false;
	}
	newActor->m_featureShape.reset(new FeatureShapeMix(shape));
	return true;
}

bool HistoryManager::redoDetachEdge(DetachEdgeOperation* op)
{
    Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
    TopoDS_Shape shape = GetSubShapeByIndex(refActor->OccShape(), TopAbs_EDGE, op->m_subShapeIndex);

    if (shape.IsNull())
    {
        std::cout << "HistoryManager::redoDetachEdge() failed. Shape is null" << std::endl;
        return false;
    }

    TopoDS_Wire wire = TopoDS::Wire(refActor->OccShape());
    TopoDS_Edge edge = TopoDS::Edge(shape);

    if (wire.IsNull() || edge.IsNull())
    {
        std::cout << "HistoryManager::redoDetachEdge() failed. Wire or Edge is null" << std::endl;
        return false;
    }

	TopoDS_Shape remain;

	if (!RemoveEdgeFromWire(wire, edge, remain))
	{
        std::cout << "HistoryManager::redoDetachEdge() failed. RemoveEdgeFromWire() failed" << std::endl;
		return false;
	}

	m_mainWindow->RemoveActorFromRenderer(refActor);
	m_mainWindow->createBasicUnitActor(remain, true)->m_featureShape.reset(new FeatureShapeMix(remain));
	m_mainWindow->createBasicUnitActor(edge, true)->m_featureShape.reset(new FeatureShapeMix(edge));

    return true;
}

bool HistoryManager::redoDetachFace(DetachFaceOperation* op)
{
	Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
	TopoDS_Shape shape = GetSubShapeByIndex(refActor->OccShape(), TopAbs_FACE, op->m_subShapeIndex);

	if (shape.IsNull())
	{
		std::cout << "HistoryManager::redoDetachFace() failed. Shape is null" << std::endl;
		return false;
	}

	TopoDS_Face face = TopoDS::Face(shape);

	if (face.IsNull())
	{
		std::cout << "HistoryManager::redoDetachFace() failed. Face is null" << std::endl;
		return false;
	}

    TopoDS_Shape remain = removeFaceFromShape(refActor->OccShape(), face);
    if (remain.IsNull())
    {
        std::cout << "HistoryManager::redoDetachFace() failed. Remain is null" << std::endl;
        return false;
    }

	m_mainWindow->RemoveActorFromRenderer(refActor);
	m_mainWindow->createBasicUnitActor(remain, true)->m_featureShape.reset(new FeatureShapeMix(remain));
	m_mainWindow->createBasicUnitActor(face, true)->m_featureShape.reset(new FeatureShapeMix(face));

	return true;
}

bool HistoryManager::redoUncoverFace(UncoverFaceOperation* op)
{
	Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
	TopoDS_Shape shape = GetSubShapeByIndex(refActor->OccShape(), TopAbs_FACE, op->m_subShapeIndex);

	if (shape.IsNull())
	{
		std::cout << "HistoryManager::redoUncoverFace() failed. Shape is null" << std::endl;
		return false;
	}

	TopoDS_Face face = TopoDS::Face(shape);

	if (face.IsNull())
	{
		std::cout << "HistoryManager::redoUncoverFace() failed. Face is null" << std::endl;
		return false;
	}

	TopoDS_Shape remain = RemoveFaceAndKeepBoundary(refActor->OccShape(), face);
	if (remain.IsNull())
	{
		std::cout << "HistoryManager::redoUncoverFace() failed. Remain is null" << std::endl;
		return false;
	}

	m_mainWindow->RemoveActorFromRenderer(refActor);
	m_mainWindow->createBasicUnitActor(remain, true)->m_featureShape.reset(new FeatureShapeMix(remain));

	return true;
}

bool HistoryManager::redoCoverFace(CoverFaceOperation* op)
{
    Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);

    TopoDS_Solid solidShape = CloseOpenShellToSolid(refActor->OccShape());
	if (solidShape.IsNull())
	{
		std::cout << "HistoryManager::redoCoverFace() failed. Remain is null" << std::endl;
		return false;
	}

	m_mainWindow->RemoveActorFromRenderer(refActor);
	m_mainWindow->createBasicUnitActor(solidShape, true)->m_featureShape.reset(new FeatureShapeMix(solidShape));

    return true;
}

bool HistoryManager::redoMoveEdge(MoveEdgeOperation* op)
{
	Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
	TopoDS_Shape shape = GetSubShapeByIndex(refActor->OccShape(), TopAbs_EDGE, op->m_subShapeIndex);

	if (shape.IsNull())
	{
		std::cout << "HistoryManager::redoMoveEdge() failed. Shape is null" << std::endl;
		return false;
	}

	TopoDS_Edge edge = TopoDS::Edge(shape);

	if (edge.IsNull())
	{
		std::cout << "HistoryManager::redoMoveEdge() failed. Edge is null" << std::endl;
		return false;
	}

    TopoDS_Shape newShape = OffsetEdgeInPlanarShape(refActor->OccShape(), edge, op->m_moveDistance);

    if (newShape.IsNull())
    {
        std::cout << "HistoryManager::redoMoveEdge() failed. New shape is null" << std::endl;
        return false;
    }

	m_mainWindow->RemoveActorFromRenderer(refActor);
	m_mainWindow->createBasicUnitActor(newShape, true)->m_featureShape.reset(new FeatureShapeMix(newShape));

    return true;
}

bool HistoryManager::redoMoveFace(MoveFaceOperation* op)
{
	Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);
	TopoDS_Shape shape = GetSubShapeByIndex(refActor->OccShape(), TopAbs_FACE, op->m_subShapeIndex);

	if (shape.IsNull())
	{
		std::cout << "HistoryManager::redoMoveFace() failed. Shape is null" << std::endl;
		return false;
	}

	TopoDS_Face face = TopoDS::Face(shape);

	if (face.IsNull())
	{
		std::cout << "HistoryManager::redoMoveFace() failed. Face is null" << std::endl;
		return false;
	}



    return true;
}

bool HistoryManager::redoSection(SectionOperation* op)
{
    Handle(QIVtkSelectionPipeline) refActor = GetActorFromIndex(m_mainWindow->GetCachedActors(), op->m_shapeIndex);

    TopoDS_Shape sectionShape = CreateSectionFromSolid(refActor->OccShape(), op->m_planeIndex);

	if (sectionShape.IsNull())
	{
		std::cout << "HistoryManager::redoSection() failed. Shape is null" << std::endl;
		return false;
	}

    m_mainWindow->createBasicUnitActor(sectionShape, true)->m_featureShape.reset(new FeatureShapeMix(sectionShape));

    return true;
}

void HistoryManager::redoUpdateItemState()
{
	// 如果是最新version，则新加item
	if (isLatestVersion())
	{
		QStandardItem* item(new QStandardItem(m_currentVersion->m_operation->operationName));
		item->setCheckable(true);
		item->setCheckState(Qt::Checked);
		item->setTextAlignment(Qt::AlignCenter);
		item->setData(QVariant::fromValue<QPointer<QShapeVersion>>(m_currentVersion), Qt::UserRole);
		m_listModel->appendRow(item);
	}
	// 不是最新就设置checked
	else
	{
		QStandardItem* item = m_listModel->item(m_itemIndex + 1, 0);
		bNotOccurItemChangeEvent = true;
		item->setCheckState(Qt::Checked);
		bNotOccurItemChangeEvent = false;
	}
    m_itemIndex++;
}

void HistoryManager::undoUpdateItemState()
{
	// 将item check state设置为Unchecked
	QStandardItem* item = m_listModel->item(m_itemIndex, 0);
	bNotOccurItemChangeEvent = true;
	item->setCheckState(Qt::Unchecked);
	bNotOccurItemChangeEvent = false;
	m_itemIndex--;
}

void HistoryManager::processSingleClick()
{
    if (bItemChangedEventOccurred)
    {
        bItemChangedEventOccurred = false;
        return;
    }
    //std::cout << "on item clicked" << std::endl;
    if (tempActor)
    {
        m_mainWindow->RemoveActorFromRenderer(tempActor);
    }

    if (m_mainWindow->bHasSubWidget)
    {
        return;
    }

    if (!pendingIndex.isValid())
    {
        return;
    }

    if (pendingIndex.row() > m_itemIndex)
    {
        return;
    }

    // 从模型中获取 QStandardItem
    QStandardItem* clickItem = m_listModel->itemFromIndex(pendingIndex);
    if (!clickItem)
    {
        return;
    }

    // 获取数据
    QVariant var = clickItem->data(Qt::UserRole);
    QPointer<QShapeVersion> shapeVersion = var.value<QPointer<QShapeVersion>>();

    if (!shapeVersion)
    {
        std::cout << "onItemClicked invalid data." << std::endl;
        return;
    }

    EOperationType operationType = shapeVersion->m_operation->m_operationType;
    // 删除操作不做回溯
    if (operationType == EOperationType::Delete || operationType == EOperationType::None)
    {
        return;
    }

    std::shared_ptr<FeatureShape> clickFeatureShape = getFeatureShape(shapeVersion, pendingIndex.row());

    if (clickFeatureShape == nullptr)
    {
        qDebug() << "onItemClicked: get faeture fail!" << shapeVersion->m_operation->operationName;
        return;
    }

    // 查看当前是否存在这个特征
    bool bFind = false;
    for (const std::shared_ptr<FeatureShape>& shape : m_currentFeatureShapes)
    {
        if (shape->IsEqual(*clickFeatureShape))
        {
            bFind = true;
            break;
        }
    }
    // 若存在则会高亮，并实际选择它
    if (bFind)
    {
        Handle(QIVtkSelectionPipeline) actor = m_mainWindow->GetActorFromFeatureShape(clickFeatureShape);
        if (actor)
        {
            m_mainWindow->SelectActor(actor, true);
        }
    }
    // 若不存在则会创建一个暂时的actor，然后高亮它，但只做展示用途
    else
    {
        if (tempActor)
        {
            m_mainWindow->RemoveActorFromRenderer(tempActor);
        }

        tempActor = m_mainWindow->createActorFromFeatureShape(clickFeatureShape.get(), false);
        tempActor->Actor()->GetProperty()->SetColor(Colors::ActorSelected);
        tempActor->Actor()->GetProperty()->SetOpacity(0.5f);
        m_mainWindow->FlushRender();
    }
}

void HistoryManager::editVersion(QPointer<QShapeVersion> version)
{
    editVersion(version, getItemRow(version));
}

void HistoryManager::editVersion(QPointer<QShapeVersion> version, int versionItemRow)
{
	if (!version || versionItemRow == -1)
	{
		std::cout << "onItemDoubleClicked invalid data." << std::endl;
		return;
	}

	EOperationType operationType = version->m_operation->m_operationType;
	// 删除操作不做回溯
	if (operationType == EOperationType::Delete || operationType == EOperationType::None)
	{
		return;
	}

	// qDebug() << "onItemdoubleClicked: " << shapeVersion->m_operation->operationName;

	// 退回点击的version
	m_mainWindow->RemoveAllActorsFromRenderer();
	bNotOccurItemChangeEvent = true;
    RedoTargetIndex = versionItemRow;
	while (m_itemIndex != versionItemRow)
	{
		//m_listModel->removeRow(m_listModel->rowCount() - 1);
		m_listModel->item(m_itemIndex)->setCheckState(Qt::Unchecked);
		m_itemIndex--;

		futureVersion.push_back(m_currentVersion);
		m_currentVersion = historyVersion.back();
		historyVersion.pop_back();
	}
	//m_listModel->removeRow(m_listModel->rowCount() - 1);
	m_listModel->item(m_itemIndex)->setCheckState(Qt::Unchecked);
	m_itemIndex--;
	bNotOccurItemChangeEvent = false;

	futureVersion.push_back(m_currentVersion);
	m_currentVersion = historyVersion.back();
	historyVersion.pop_back();

	// 创建对应版本的actor
	for (auto& item : m_currentVersion->m_featureShapes)
	{
		Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createBasicUnitActor(item->_shape, true);
		actor->m_featureShape = item;
	}
	m_currentFeatureShapes = m_mainWindow->GetCurrentFeatureShapes();

	// 开始redo
	// 1.创建对应的widget-----（done!）
	// 2.widget需要根据operation的参数进行初始化-----（done! create完成了初始化）
	// 3.widget完成操作之后在applyOperation中进行下一步逻辑（delete传进来的operation redo剩下的version）-----（done!）
	// 4.widget cancel则需要还原现场（改造SubWidgetClose，判断是否正常关闭，false则触发history的还原逻辑）-----（done!）

	m_mainWindow->redoOperation(m_currentVersion->m_operation);
	bIsRedo = true;
}

int HistoryManager::getItemRow(QPointer<QShapeVersion> version)
{
    for (int i = 0; i < m_listModel->rowCount(); i++)
    {
        QStandardItem* item = m_listModel->item(i);

		// 获取数据
		QVariant var = item->data(Qt::UserRole);
		QPointer<QShapeVersion> shapeVersion = var.value<QPointer<QShapeVersion>>();

        if (shapeVersion == version)
        {
            return i;
        }
    }

    return -1;
}

std::shared_ptr<FeatureShape> HistoryManager::getFeatureShape(QPointer<QShapeVersion> version, int versionItemRow)
{
    if (!version || versionItemRow == -1)
    {
        return nullptr;
    }

    /*
     * 能根据点击的version推测是该版本生成的featureshape是哪一个
     * 找到下个version的featureshape的最后一个元素
     * 若下一个version为空，那么就是m_currentVersion的featureshape的最后一个元素。
    */
    // 判断点击的是否为最后一个version
    std::shared_ptr<FeatureShape> featureShape;
    if (m_listModel->rowCount() == versionItemRow + 1)
    {
        // 从m_currentVersion中获取
        featureShape = m_currentVersion->m_featureShapes.back();
    }
    else
    {
        // 从模型中获取 QStandardItem
        QStandardItem* clickItem = m_listModel->item(versionItemRow + 1);
        if (!clickItem)
        {
            std::cout << "version get feature shape fail: last item is invaild data" << std::endl;
            return nullptr;
        }

        // 获取数据
        QVariant var = clickItem->data(Qt::UserRole);
        QPointer<QShapeVersion> shapeVersion = var.value<QPointer<QShapeVersion>>();
        if (!shapeVersion)
        {
            std::cout << "version get feature shape fail: last version is invaild data" << std::endl;
            return nullptr;
        }
        featureShape = shapeVersion->m_featureShapes.back();
    }

    return featureShape;
}

std::shared_ptr<FeatureShape> HistoryManager::getFeatureShape(QPointer<QShapeVersion> version)
{
    return getFeatureShape(version, getItemRow(version));
}

QPointer<QShapeVersion> HistoryManager::getVersion(Handle(QIVtkSelectionPipeline) actor, bool bIncludeFuture)
{
    for (const QPointer<QShapeVersion>& version : historyVersion)
    {
        if (actor->m_featureShape->IsEqual(*getFeatureShape(version)))
        {
            return version;
        }
    }

    if (bIncludeFuture)
    {
        for (const QPointer<QShapeVersion>& version : futureVersion)
        {
            if (actor->m_featureShape->IsEqual(*getFeatureShape(version)))
            {
                return version;
            }
        }
    }

    return nullptr;
}

void HistoryManager::saveMixShape(const std::vector<std::shared_ptr<FeatureShape>>& shapes)
{
    for (const auto& shape : shapes)
    {
		if (shape->_featureType == EFeatureType::Mix)
		{
			FeatureShapeMix* mix = static_cast<FeatureShapeMix*>(shape.get());
			if (mix->_shapeFileName != "None")
			{
				RWShapeSerializeManager::SaveShape(mix->_shapeFileName, mix->_shape);
			}
		}
    }
}

void HistoryManager::onItemClicked(const QModelIndex& index)
{
	pendingIndex = index;  // 记录待处理的单击索引
	clickTimer->start();   // 启动延迟判断
}

void HistoryManager::onItemDoubleClicked(const QModelIndex& index)
{
    clickTimer->stop();    // 取消延迟的单击处理
	if (bItemChangedEventOccurred)
	{
		bItemChangedEventOccurred = false;
		return;
	}
    //std::cout << "on item double clicked" << std::endl;
	if (tempActor)
	{
		m_mainWindow->RemoveActorFromRenderer(tempActor);
	}

    if (m_mainWindow->bHasSubWidget)
    {
        return;
    }

    if (!index.isValid())
    {
        return;
    }

    // 从模型中获取 QStandardItem
    QStandardItem* clickItem = m_listModel->itemFromIndex(index);
    if (!clickItem)
    {
        return;
    }

	if (m_itemIndex < clickItem->row())
	{
		return;
	}

	// 获取数据
	QVariant var = clickItem->data(Qt::UserRole);
	QPointer<QShapeVersion> shapeVersion = var.value<QPointer<QShapeVersion>>();

    editVersion(shapeVersion, clickItem->row());
}

void HistoryManager::saveOperations()
{
	// 如果没有修改过，则不保存
	if (!bIsDirty)
	{
		return;
	}

    std::ofstream out("save/" + std::to_string(m_startTime) + ".bin", std::ios::binary);
    if (!out) return;

    // 写入 operation 数量与 current operation 的 index
    uint operationCount = futureVersion.size() + historyVersion.size();
    uint currentVersionIndex = historyVersion.size();
    out.write(reinterpret_cast<const char*>(&operationCount), sizeof(operationCount));
    out.write(reinterpret_cast<const char*>(&currentVersionIndex), sizeof(currentVersionIndex));

    // 历史 operation 序列化
    for (const auto& version : historyVersion)
    {
        if (version->m_operation)
        {
            version->m_operation->serialize(out);
        }
        saveMixShape(version->m_featureShapes);
    }
    // 当前 operation 序列化
    if (m_currentVersion->m_operation)
    {
        m_currentVersion->m_operation->serialize(out);
    }
    // 未来 operation 序列化
    for (const auto& version : futureVersion)
    {
        if (version->m_operation)
        {
            version->m_operation->serialize(out);
        }
        saveMixShape(version->m_featureShapes);
    }

    // 查找所有mix shape并save
    saveMixShape(m_currentFeatureShapes);

    out.close();

    bIsDirty = false;
    std::cout << "save history success" << std::endl;
}

void HistoryManager::loadOperations(const std::string& filename)
{
    std::ifstream in(filename, std::ios::binary);
    if (!in) return;

    uint operationCount;
    uint currentVersionIndex;
    in.read(reinterpret_cast<char*>(&operationCount), sizeof(operationCount));
    in.read(reinterpret_cast<char*>(&currentVersionIndex), sizeof(currentVersionIndex));

    for (uint i = 0; i < operationCount; i++)
    {
		// 读取操作类型
		EOperationType type;
		in.read(reinterpret_cast<char*>(&type), sizeof(type));

        auto op = ShapeOperationFactory::CreateOperation(type);
		if (op)
		{
			op->deserialize(in);
            m_currentVersion->m_operation = op;
			// 表达式
			m_expressionManager->AddExpression(m_currentVersion);
            redo();
		}
    }

    unsigned int undoCount = operationCount - currentVersionIndex;
    while (undoCount)
    {
        undo();
        undoCount--;
    }
    std::cout << "load history success" << std::endl;
}